<?php
/**
 * CRMLite Common Functions
 *
 * @final
 * @package Crmlite_App
 * @version $Id: Function.php 55 2007-09-09 12:44:28Z etng2004 $
 * @copyright 2006-2007 ETE.CN
 * @author Yi BO  <etng2004@gmail.com>
 * @license PHP Version 3.0 {@link http://www.php.net/license/3_0.txt}
 */

/**
 * 将都好分割的字符串转化为数组
 *
 * @param string $list
 * @return array
 */
function list2array($list)
{
    return explode(',', trim($list, ','));
}

/**
 * 将数组转化为逗号分隔的字符串
 *
 * @param array $array
 * @return string
 */
function array2list($array)
{
    return ',' . implode(',', $array) . ',';
}

if (! function_exists("array_fill_keys"))
{
    /**
	 * Fill an array with values, specifying keys
	 * Fills an array with the value of the value parameter,
	 * using the values of the keys array as keys.
	 *
	 * @param array $keys		Array of values that will be used as keys
	 * @param mixed $value		Either an string or an array of values
	 * @return array
	 */
    function array_fill_keys(array $keys, $value)
    {
        return array_combine($keys, array_fill(0, count($keys), $value));
    }
}


/**
 * 解析 $args 为数组参数
 *
 * @param mixed $args       输入参数控制，可以是对象、数组或字符串
 * @param array $default
 * @return unknown
 */
function parse_args( $args, array $default = array() )
{
    if ( is_object($args) )
    {
        $r = get_object_vars($args);
    }
    else if ( is_array( $args ) )
    {
        $r =& $args;
    }
    else
    {
        parse_str( $args, $r );
    }
    return array_merge( $defaults, $r );
}

/**
 * 字符串截取函数，兼容UTF-8
 *
 * @param string $s		是要处理的字符串
 * @param int $length	为截取的长度(即字数)
 * @return string
 */
function truncate($s, $length)
{
    $r='';
    $i=0;
    $n=0;
    /*字符串的字节数*/
    $str_length = strlen($s);
    while(($n < $length)and($i <= $str_length))
    {
        $temp_str=substr($s, $i, 1);
        /*得到字符串中第$i位字符的ASCII码*/
        $ascnum=ord($temp_str);
        /*如果ASCII位高与224*/
        if($ascnum >= 224)
        {
            /*根据UTF-8编码规范，将3个连续的字符计为单个字符*/
            $r = $r . substr($s, $i, 3);
            /*实际Byte计为3*/
            $i = $i + 3;
            /*字串长度计1*/
            $n++;
        }
        /*如果ASCII位高与192*/
        elseif($ascnum >= 192)
        {
            /*根据UTF-8编码规范，将2个连续的字符计为单个字符*/
            $r = $r . substr($s, $i, 2);
            /*实际Byte计为2*/
            $i = $i + 2;
            /*字串长度计1*/
            $n++;
        }
        /*如果是大写字母，*/
        elseif($ascnum >= 65 && $ascnum <= 90)
        {
            $r = $r . substr($s, $i, 1);
            /*实际的Byte数仍计1个*/
            $i = $i + 1;
            /*但考虑整体美观，大写字母计成一个高位字符*/
            $n++;
        }
        /*其他情况下，包括小写字母和半角标点符号，*/
        else
        {
            $r = $r . substr($s, $i, 1);
            /*实际的Byte数计1个*/
            $i = $i + 1;
            /*小写字母和半角标点等于半个高位字符宽...*/
            $n = $n + 0.5;
        }
    }
    if($str_length/3> $length)
    {
        /*超过长度时在尾处加上省略号*/
        $r = $r . "...";
    }
    return$r;
}

/**
 * 修正字符串中的 EOL,以便统一
 *
 * @param string $s         字符串
 * @param bool $unix_style  Unix风格 = \n ,否则采用本地风格 PHP_EOL
 * @return string
 */
function str_eol($s, $unix_style = false)
{
    if($unix_style)
    {
        $s = str_replace(array("\r\n", "\r"), "\n", $s);
    }
    else
    {
        $s = str_replace(array("\r\n", "\r", "\n"), PHP_EOL, $s);
    }
    return $s;
}

/**
 * 根据条件决定是否进行 gzip 压缩输出
 *
 * @return bool
 */
function gzip_ob_start() {
    if ( ( ini_get( 'zlib.output_compression' ) == 'On' || ini_get( 'zlib.output_compression_level' ) > 0 ) || ini_get( 'output_handler' ) == 'ob_gzhandler' )
    {
        return false;
    }

    if ( !extension_loaded( 'zlib' ) ) return false;
    ob_start( 'ob_gzhandler' );
    return true;
}

/**
 * 输出禁止缓存的Headers
 *
 */
function nocache_headers()
{
    @ header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
    @ header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    @ header('Cache-Control: no-cache, must-revalidate, max-age=0');
    @ header('Pragma: no-cache');
}

/**
 * 输出缓存js的Headers
 *
 * @param string $charset       字符编码
 * @param int $expiresOffset    缓存时间， 秒为单位
 */
function cache_javascript_headers($charset = 'UTF-8', $expiresOffset = 864000)
{
    // 864000 = 10 days
    header("Content-Type: text/javascript; charset={$charset}");
    header("Vary: Accept-Encoding"); // Handle proxies
    header("Expires: " . gmdate("D, d M Y H:i:s", time() + $expiresOffset) . " GMT");
}

/**
 * 根据文件名获得文件的类型
 *
 * @param string $filename      文件名
 * @param array $mimes          自定义的MIME
 * @return array   返回数组，ext 键指扩展名, type 指文件类型MIME
 */
function check_filetype($filename, $mimes = null) {
    // Accepted MIME types are set here as PCRE unless provided.
    $mimes = is_array($mimes) ? $mimes : array (
    'jpg|jpeg|jpe' => 'image/jpeg',
    'gif' => 'image/gif',
    'png' => 'image/png',
    'bmp' => 'image/bmp',
    'tif|tiff' => 'image/tiff',
    'ico' => 'image/x-icon',
    'asf|asx|wax|wmv|wmx' => 'video/asf',
    'avi' => 'video/avi',
    'mov|qt' => 'video/quicktime',
    'mpeg|mpg|mpe' => 'video/mpeg',
    'txt|c|cc|h' => 'text/plain',
    'rtx' => 'text/richtext',
    'css' => 'text/css',
    'htm|html' => 'text/html',
    'mp3|mp4' => 'audio/mpeg',
    'ra|ram' => 'audio/x-realaudio',
    'wav' => 'audio/wav',
    'ogg' => 'audio/ogg',
    'mid|midi' => 'audio/midi',
    'wma' => 'audio/wma',
    'rtf' => 'application/rtf',
    'js' => 'application/javascript',
    'pdf' => 'application/pdf',
    'doc' => 'application/msword',
    'pot|pps|ppt' => 'application/vnd.ms-powerpoint',
    'wri' => 'application/vnd.ms-write',
    'xla|xls|xlt|xlw' => 'application/vnd.ms-excel',
    'mdb' => 'application/vnd.ms-access',
    'mpp' => 'application/vnd.ms-project',
    'swf' => 'application/x-shockwave-flash',
    'class' => 'application/java',
    'tar' => 'application/x-tar',
    'zip' => 'application/zip',
    'gz|gzip' => 'application/x-gzip',
    'exe' => 'application/x-msdownload',
    // openoffice formats
    'odt' => 'application/vnd.oasis.opendocument.text',
    'odp' => 'application/vnd.oasis.opendocument.presentation',
    'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
    'odg' => 'application/vnd.oasis.opendocument.graphics',
    'odc' => 'application/vnd.oasis.opendocument.chart',
    'odb' => 'application/vnd.oasis.opendocument.database',
    'odf' => 'application/vnd.oasis.opendocument.formula',

    );

    $type = false;
    $ext = false;

    foreach ($mimes as $ext_preg => $mime_match) {
        $ext_preg = '!\.(' . $ext_preg . ')$!i';
        if ( preg_match($ext_preg, $filename, $ext_matches) ) {
            $type = $mime_match;
            $ext = $ext_matches[1];
            break;
        }
    }

    return compact('ext', 'type');
}
/**
 * 自动进行链接，如http,email等
 *
 * @param string $ret
 * @return string
 */
function auto_links($text) {
    $text = ' ' . $text;
    // in testing, using arrays here was found to be faster
    $text = preg_replace(
    array(
    '#([\s>])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is',
    '#([\s>])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is',
    '#([\s>])([a-z0-9\-_.]+)@([^,< \n\r]+)#i'),
    array(
    '$1<a href="$2" rel="nofollow">$2</a>',
    '$1<a href="http://$2" rel="nofollow">$2</a>',
    '$1<a href="mailto:$2@$3">$2@$3</a>'),$text);
    // this one is not in an array because we need it to run last, for cleanup of accidental links within links
    $text = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $text);
    $text = trim($text);
    return $text;
}

function auto_pre($text) {
    $text = str_replace('<br />', '', $text);
    $text = str_replace('<p>', "\n", $text);
    $text = str_replace('</p>', '', $text);
    return $text;
}
/**
 * 自动格式化文本，进行分段等
 *
 * @param string $pee       输入文本
 * @param unknown_type $br
 * @return unknown
 */
function auto_pragraphs($pee, $br = 1)
{
    $pee = $pee . "\n"; // just to make things a little easier, pad the end
    $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee);
    // Space things out a little
    $allblocks = '(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|map|area|blockquote|address|math|style|input|p|h[1-6]|hr)';
    $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee);
    $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
    $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines
    $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates
    $pee = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $pee); // make paragraphs, including one at the end
    $pee = preg_replace('|<p>\s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace
    $pee = preg_replace('!<p>([^<]+)\s*?(</(?:div|address|form)[^>]*>)!', "<p>$1</p>$2", $pee);
    $pee = preg_replace( '|<p>|', "$1<p>", $pee );
    $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag
    $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists
    $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
    $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
    $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee);
    $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
    if ($br)
    {
        $pee = preg_replace('/<(script|style).*?<\/\\1>/se', 'str_replace("\n", "<WPPreserveNewline />", "\\0")', $pee);
        $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks
        $pee = str_replace('<WPPreserveNewline />', "\n", $pee);
    }
    $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);
    $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee);
    if (strpos($pee, '<pre') !== false)
    $pee = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '</pre>' ", $pee);
    $pee = preg_replace( "|\n</p>$|", '</p>', $pee );

    return $pee;
}

define('SPECIAL_QUOTE_DOUBLE', 2);
define('SPECIAL_QUOTE_SINGLE', 1);
define('SPECIAL_QUOTE_BOTH', 3);
define('SPECIAL_QUOTE_NONE', 0);
/**
 * 转换文字中的特殊字符串
 *
 * Like htmlspecialchars except don't double-encode HTML entities
 *
 * @param string $text      输入文字
 * @param int    $quotes    转换的引号类型
 * @return string
 */
function specialchars( $text, $quotes = SPECIAL_QUOTE_BOTH )
{
    $text = str_replace('&&', '&#038;&', $text);
    $text = str_replace('&&', '&#038;&', $text);
    $text = preg_replace('/&(?:$|([^#])(?![a-z1-4]{1,8};))/', '&#038;$1', $text);
    $text = str_replace('<', '&lt;', $text);
    $text = str_replace('>', '&gt;', $text);
    if ( $quotes == SPECIAL_QUOTE_DOUBLE)
    {
        $text = str_replace('"', '&quot;', $text);
    }
    else if ($quotes == SPECIAL_QUOTE_SINGLE )
    {
        $text = str_replace("'", '&#039;', $text);
    }
    else if ( $quotes == SPECIAL_QUOTE_BOTH )
    {
        $text = str_replace('"', '&quot;', $text);
        $text = str_replace("'", '&#039;', $text);
    }
    return $text;
}

/**
 * 获得规范的文件名
 *
 * @param string $name
 * @return string
 */
function sanitize_file_name( $name )
{
    $name = strtolower( $name );
    $name = preg_replace('/&.+?;/', '', $name); // kill entities
    $name = str_replace( '_', '-', $name );
    $name = preg_replace('/[^a-z0-9\s-.]/', '', $name);
    $name = preg_replace('/\s+/', '-', $name);
    $name = preg_replace('|-+|', '-', $name);
    $name = trim($name, '-');
    return $name;
}

/**
 * 输出方便人们阅读的文件大小
 * technically the correct unit names for powers of 1024 are KiB, MiB etc
 *  see http://en.wikipedia.org/wiki/Byte
 *
 * @see http://en.wikipedia.org/wiki/Byte
 * @param int $bytes            字节数
 * @param int $decimals         精确到小数点后位数
 */
function human_filesize($bytes, $decimals = 0)
{
    $quant = array(
    'TB' => pow(1024, 4),
    'GB' => pow(1024, 3),
    'MB' => pow(1024, 2),
    'kB' => pow(1024, 1),
    'B'  => pow(1024, 0),
    );

    foreach ($quant as $unit => $mag)
    {
        if ( intval($bytes) >= $mag )
        {
            return number_format($bytes/$mag, $decimals, '.', '') . ' ' . $unit ;
        }
    }
}
/**
 * 输出方便人们阅读的时间差异
 *
 * @param int $seconds  时间差异秒数
 * @param int $deep     比较级数，显示两级差不多了如两天4小时之前
 * @param array $lang   相应的语言文件，需要自定义时有用
 * @return string       表示出的字符串
 */
function human_timediff($seconds, $deep = 2, $lang = array())
{
    $lang = array(
    'negative' => '%s之前',
    'positive' => '%s之后',
    'periods' => array (
    'decade' => '百年',
    'year'   => '年',
    'month'  => '个月',
    'week'   => '周',
    'day'    => '天',
    'hour'   => '小时',
    'minute' => '分',
    'second' => '秒',
    )
    );
    $periods = array (
    'decade' => 315705600,
    'year'   => 31570560,
    'month'  => 2630880,
    'week'   => 604800,
    'day'    => 86400,
    'hour'   => 3600,
    'minute' => 60,
    'second' => 1,
    );
    $s = '';
    $num = abs($seconds);
    $i = 1;
    foreach ($periods as $period => $length)
    {
        if(intval($num) >= $length)
        {
            $count = floor($num / $length);
            $num = $num % $length;
            $s .= $count . ' ' .  $lang['periods'][$period];
            if($i++>=$deep)break;
        }
    }
    $s = sprintf($lang[$seconds?'negative':'positive'], $s);
    //return compact('seconds', 'num', 's');
    return $s;
}


